package com.example.service;

import com.example.domain.valueobject.Money;
import com.example.domain.valueobject.Quantity;

import java.math.BigDecimal;
import java.util.List;

/**
 * 价格计算服务接口
 * 纯业务逻辑，负责价格计算和折扣应用
 * 
 * @author Means
 * @since 2025-10-27
 */
public interface PricingService {
    
    // ==================== 价格计算 ====================
    
    /**
     * 计算商品行金额（数量 × 单价）
     * 
     * @param quantity 数量
     * @param unitPrice 单价
     * @return 行金额
     */
    Money calculateLineAmount(Quantity quantity, Money unitPrice);
    
    /**
     * 计算商品行金额（简化版）
     * 
     * @param quantity 数量值
     * @param unitPrice 单价金额
     * @return 行金额
     */
    Money calculateLineAmount(BigDecimal quantity, BigDecimal unitPrice);
    
    // ==================== 折扣计算 ====================
    
    /**
     * 应用单品折扣率
     * 
     * @param originalAmount 原价
     * @param discountRate 折扣率（如0.8表示8折）
     * @return 折扣后金额
     */
    Money applyDiscountRate(Money originalAmount, BigDecimal discountRate);
    
    /**
     * 应用固定折扣金额
     * 
     * @param originalAmount 原价
     * @param discountAmount 折扣金额
     * @return 折扣后金额
     */
    Money applyFixedDiscount(Money originalAmount, Money discountAmount);
    
    
    // ==================== 满减计算 ====================
    
    /**
     * 计算满减折扣的减免金额
     * 封装满减计算的所有逻辑，包括判断基准选择、门槛判断、叠加计算
     * 
     * @param currentSubtotal 当前小计（折后价）
     * @param originalSubtotal 原价小计
     * @param thresholdAmount 门槛金额
     * @param reductionAmount 单次减免金额
     * @param stackable 是否可叠加
     * @param useOriginalPrice 门槛判断是否使用原价（true=用原价，false=用折后价）
     * @return 总减免金额（未满足门槛返回0）
     */
    Money calculateThresholdReduction(Money currentSubtotal, Money originalSubtotal,
                                      Money thresholdAmount, Money reductionAmount,
                                      boolean stackable, boolean useOriginalPrice);
    
    /**
     * 计算满减次数
     * 
     * @param totalAmount 总金额
     * @param thresholdAmount 满减门槛
     * @return 满减次数
     */
    int calculateThresholdCount(Money totalAmount, Money thresholdAmount);
    
    // ==================== 总价计算 ====================
    
    /**
     * 计算购物车总价（多个商品行金额之和）
     * 
     * @param lineAmounts 商品行金额列表
     * @return 总金额
     */
    Money calculateSubtotal(List<Money> lineAmounts);
    
    /**
     * 计算最终应付金额（小计 - 折扣）
     * 
     * @param subtotal 小计
     * @param discountTotal 总折扣金额
     * @return 应付金额
     */
    Money calculatePayableAmount(Money subtotal, Money discountTotal);
    
    // ==================== 促销规则验证 ====================
    
    /**
     * 检查金额是否满足满减门槛
     * 
     * @param amount 金额
     * @param threshold 门槛
     * @return 是否满足
     */
    boolean meetsThreshold(Money amount, Money threshold);
    
    /**
     * 验证折扣率是否有效（0 < rate <= 1）
     * 
     * @param discountRate 折扣率
     * @return 是否有效
     */
    boolean isValidDiscountRate(BigDecimal discountRate);
    
    /**
     * 验证折扣金额是否有效（0 < discount < original）
     * 
     * @param discountAmount 折扣金额
     * @param originalAmount 原金额
     * @return 是否有效
     */
    boolean isValidDiscountAmount(Money discountAmount, Money originalAmount);
}

